/*
    SEL - Simple DirectMedia Layer Extension Library
    Copyright (C) 2001 Matej Knopp <knopp@users.sf.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef __sel_rect_h__
#define __sel_rect_h__

#include "sdl.h"

namespace SEL
{

//! Extended version of SDL::Rect.
/*!
  This class enhances the SDL::Rect by a number of constructors,
  functions for intersections and for unions.
  Since this class is derived from SDL::Rect it can be used
  in any contents where SDL::Rect can be.
 */
class Rect : public SDL::Rect
{
public:
	//! Create a rectangle initialized from given values.
	Rect (Sint16 _x = 0, Sint16 _y = 0, Uint16 _w = 0, Uint16 _h = 0);

	//! Create a rectangle with given width and height.
	Rect (Uint16 _w, Uint16 _h);

	//! Create a rectangle initialized from and SDL::Rect rectangle.
	Rect (const SDL::Rect &rect);

	//! Copy constructor.
	Rect (const SEL::Rect &rect);

	//! Set the value of an SEL::Rect to that of an existing SDL::Rect.
	SEL::Rect & operator= (const SDL::Rect & rect);

	//! Compare two rectangles.
	bool operator== (const SDL::Rect &rect) const;

	//! Return an intersection of two rectangles.
	/*!
	  \param rect1, rect2 rectangles
	 */
	static Rect intersect (const Rect & rect1, const Rect & rect2);

	//! Return an union of two rectangles.
	/*!
	  \param rect1, rect2 rectangles
	 */
	static Rect unite (const Rect & rect1, const Rect & rect2);

	//! Intersect a rectangle with another one.
	void intersect (const Rect & rect);

	//! Unite a rectangle with another one.
	void unite (const Rect & rect);
};

//////////////////////////////////////////////////////////////////
//////////////////////// INLINE FUNCTIONS ////////////////////////
//////////////////////////////////////////////////////////////////

inline
Rect::Rect (Sint16 _x, Sint16 _y, Uint16 _w, Uint16 _h)
{
	x = _x;
	y = _y;
	w = _w;
	h = _h;
}

inline
Rect::Rect (Uint16 _w, Uint16 _h)
{
	x = y = 0;
	w = _w;
	h = _h;
}

inline
Rect::Rect (const SDL::Rect &rect)
{
	operator= (rect);
}

inline
Rect::Rect (const SEL::Rect &rect)
{
	*this = rect;
}

inline SEL::Rect &
Rect::operator= (const SDL::Rect & rect)
{
	x = rect.x;
	y = rect.y;
	w = rect.w;
	h = rect.h;
	return *this;
}

inline bool
Rect::operator== (const SDL::Rect &rect) const
{
	return (x == rect.x && y == rect.y && w == rect.w && h == rect.h);
}

#define ___MIN(a,b) (a < b ? a : b)
#define ___MAX(a,b) (a > b ? a : b)

inline Rect
Rect::intersect (const Rect & rect1, const Rect & rect2)
{
        Rect rect;
	Sint32 i;
	rect.x = ___MAX (rect1.x, rect2.x);
	rect.y = ___MAX (rect1.y, rect2.y);
	i = ___MIN (rect1.x + rect1.w - 1, rect2.x + rect2.w - 1) - rect.x + 1;
	rect.w = i > 0 ? i : 0;
	i = ___MIN (rect1.y + rect1.h - 1, rect2.y + rect2.h - 1) - rect.y + 1;
	rect.h = i > 0 ? i : 0;
	return rect;
}

inline Rect
Rect::unite (const Rect & rect1, const Rect & rect2)
{
	Rect rect;
	rect.x = ___MIN (rect1.x, rect2.x);
	rect.y = ___MIN (rect1.y, rect2.y);
	rect.w = ___MAX (rect1.x + rect1.w - 1, rect2.x + rect2.w - 1)
		 - rect.x + 1;
	rect.h = ___MAX (rect1.y + rect1.h - 1, rect2.y + rect2.h - 1)
		 - rect.y + 1;
	return rect;
}

inline void
Rect::intersect (const Rect & rect)
{
	*this = intersect (rect, *this);
}

inline void
Rect::unite (const Rect& rect)
{
	*this = unite (rect, *this);
}

#undef ___MIN
#undef ___MAX

} // namespace SEL

#endif // __sel_rect_h__
